package com.myk.game.gobangchess.ai.symmetric;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GameStateGenerator {

    /**
     * 根据输入的棋盘矩阵，生成并返回一个包含完整对局状态信息的 GameState 对象。
     * 该函数会调用已有的其它功能函数（如 BlockFinder, SymmetryChecker 等）来计算所有必需的状态信息。
     *
     * @param board 15x15 的棋盘矩阵。1 代表黑棋, -1 代表白棋, 0 代表空位。
     * @return 一个填充了所有当前对局状态信息的 GameState 对象。
     */
    public static GameState getGameState(int[][] board) {
        // 1. 统计棋子数量并确定当前行动方
        int blackCount = 0;
        int whiteCount = 0;
        for (int[] row : board) {
            for (int cell : row) {
                if (cell == 1) blackCount++;
                else if (cell == -1) whiteCount++;
            }
        }
        int currentPlayer = (blackCount == whiteCount) ? 1 : -1;
        int totalPieceCount = blackCount + whiteCount;

        // 2. 查找所有棋块
        Map<Integer, List<List<int[]>>> allBlocks = BlockFinder.findBlocks(board);
        int blackBlockCount = allBlocks.getOrDefault(1, Collections.emptyList()).size();
        int whiteBlockCount = allBlocks.getOrDefault(-1, Collections.emptyList()).size();

        // 3. 初始化用于存储棋块属性的数据结构
        Map<Integer, List<Boolean>> blockSymmetries = new HashMap<>();
        Map<Integer, List<int[][]>> blockBoundingBoxes = new HashMap<>();
        Map<Integer, List<Integer>> blockSizes = new HashMap<>();
        Map<Integer, List<List<int[]>>> blockSurroundingPoints = new HashMap<>();

        // 4. 遍历每种颜色的每个棋块，计算其属性
        for (Map.Entry<Integer, List<List<int[]>>> entry : allBlocks.entrySet()) {
            int color = entry.getKey();
            List<List<int[]>> blocksOfColor = entry.getValue();

            List<Boolean> symmetries = new ArrayList<>();
            List<int[][]> boundingBoxes = new ArrayList<>();
            List<Integer> sizes = new ArrayList<>();
            List<List<int[]>> surroundingPointsList = new ArrayList<>();

            for (List<int[]> block : blocksOfColor) {
                sizes.add(block.size());
                symmetries.add(SymmetryChecker.isSymmetric(block));
                boundingBoxes.add(BoundingBoxFinder.getBoundingBoxCorners(block));
                surroundingPointsList.add(SurroundingPointsFinder.getSurroundingEmptyPoints(block, board));
            }

            blockSymmetries.put(color, symmetries);
            blockBoundingBoxes.put(color, boundingBoxes);
            blockSizes.put(color, sizes);
            blockSurroundingPoints.put(color, surroundingPointsList);
        }

        // 5. 根据当前行动方的棋块状态，确定其可拉子次数
        int totalPullsAllowed = 1;
        List<Integer> currentPlayerSizes = blockSizes.get(currentPlayer);
        List<Boolean> currentPlayerSymmetries = blockSymmetries.get(currentPlayer);

        if (currentPlayerSizes != null && currentPlayerSymmetries != null) {
            for (int i = 0; i < currentPlayerSizes.size(); i++) {
                if (currentPlayerSizes.get(i) >= 5 && !currentPlayerSymmetries.get(i)) {
                    totalPullsAllowed = 2;
                    break;
                }
            }
        }

        // 6. 初始化回合开始时的状态
        boolean hasPlacedPiece = false;
        int pullsMade = 0;

        // 7. 创建并返回 GameState 对象
        return new GameState(
            currentPlayer,
            hasPlacedPiece,
            totalPullsAllowed,
            pullsMade,
            allBlocks,
            blockSymmetries,
            blockBoundingBoxes,
            blockSizes,
            blockSurroundingPoints,
            totalPieceCount,
            blackBlockCount,
            whiteBlockCount,
            board
        );
    }

    /**
     * 用于测试和验证 getGameState 函数的主函数。
     */
    public static void main(String[] args) {
        // 1. 定义一个 15x15 的测试棋盘

        int[][] board2 = {
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        };
        int[][] board = {
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        };

        // 2. 打印初始棋盘
        System.out.println("--- 初始测试棋盘 ---");
        BoardPrinter.printBoardWithIndices(board);
        System.out.println("---------------------\n");

        // 3. 调用函数获取对局状态
        GameState state = getGameState(board);

        // 4. 打印生成的对局状态的摘要信息
        System.out.println("--- 生成的对局状态摘要 ---");
        System.out.println(state);
        System.out.println("--------------------------\n");
        
        // 5. 打印详细的验证信息
        System.out.println("--- 详细验证信息 ---");
        System.out.println("当前行动方 (1:黑, -1:白): " + state.currentPlayer);
        System.out.println("总共可拉子次数: " + state.totalPullsAllowed);
        System.out.println("盘面总棋子数: " + state.totalPieceCount);
        System.out.println("黑方棋块数量: " + state.blackBlockCount);
        System.out.println("白方棋块数量: " + state.whiteBlockCount);
        
        // 验证黑棋棋块的属性
        List<List<int[]>> blackBlocks = state.allBlocks.get(1);
        if (blackBlocks != null && !blackBlocks.isEmpty()) {
            System.out.println("\n黑方棋块数量: " + blackBlocks.size());
            System.out.println("  (棋块1) 大小: " + state.blockSizes.get(1).get(2));
            System.out.println("  (棋块1) 是否对称: " + state.blockSymmetries.get(1).get(2));
        }
        System.out.println("----------------------");
    }
}